#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "cJSON.h"
#include "shmem.h"
#include "main.h"
#include <pthread.h>

#define IP "192.168.50.64"
#define PORT 8887
pthread_mutex_t resource;

// 接收线程
void *stm_recv(int client_sockfd)
{
    while (1)
    {
        pthread_mutex_lock(&resource);
        // 清空缓冲区
        char buf[1024] = {0};

        // 接收数据
        int ret = recv(client_sockfd, buf, sizeof(buf) - 1, 0);
        if (ret < 0)
        {
            perror("fail to recv");
            break;
            pthread_mutex_unlock(&resource);
        }
        else if (ret == 0)
        {
            // 客户端关闭连接
            printf("Client disconnected\n");
            break;
            pthread_mutex_unlock(&resource);
        }
        // 处理stm32发送的JSON格式并存入共享内存
        stm32_json_to_shm(buf);
        // 打印接收到的数据
        printf("client: %s\n", buf);
        pthread_mutex_unlock(&resource);
    }
    return NULL;
}

// 从共享内存采集数据
struct std_node *get_data_from_shm(void)
{
    struct shm_param stm_senor;
    shm_init(&stm_senor, "data", 1024);
    int *num = (int *)shm_getaddr(&stm_senor);
    struct std_node *ptr = (struct std_node *)(num + 1);
    return ptr;
}

// 处理stm32发送的JSON格式并存入共享内存
void stm32_json_to_shm(char *json)
{
    // 解析JSON字符串
    cJSON *root = cJSON_Parse(json);

    if (NULL == root)
    {
        printf("fail to cJSON_Parse\n");
        return;
    }
    cJSON *data = cJSON_GetObjectItem(root, "data");
    // 打开共享内存
    struct std_node *ptr = get_data_from_shm();
    printf("共享内存打开成功\n");
    for (int i = 0; i < cJSON_GetArraySize(data); i++)
    {
        cJSON *data_i = cJSON_GetArrayItem(data, i);
        cJSON *key_int = cJSON_GetObjectItem(data_i, "key");
        int key;
        sscanf(key_int->valuestring, "%d", &key);
        cJSON *val = cJSON_GetObjectItem(data_i, "val");
        while(key != ptr->key)
        {
            ptr++;
        }
        // 判断类型
        if (ptr->type == 1) // bool
        {
            int value;
            sscanf(val->valuestring, "%d", &value);
            ptr->old_val.b_val = ptr->new_val.b_val;
            ptr->new_val.b_val = value;
            printf("key:%d,val:%d\n",ptr->key,ptr->new_val.b_val);//测试
        }
        else if (ptr->type == 2) // int
        {
            int value;
            sscanf(val->valuestring, "%d", &value);
            ptr->old_val.i_val = ptr->new_val.i_val;
            ptr->new_val.i_val = value;
            printf("key:%d,val:%d\n",ptr->key,ptr->new_val.i_val);//测试
        }
        else if (ptr->type == 3) // float
        {
            float value;
            sscanf(val->valuestring, "%f", &value);
            ptr->old_val.f_val = ptr->new_val.f_val;
            ptr->new_val.f_val = value;
            printf("key:%d,val:%f\n",ptr->key,ptr->new_val.f_val);//测试
        }
        printf("存储成功\n");
        ptr++;
    }
}

int main(int argc, char const *argv[])
{
    // 创建TCP服务器
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("fail to socket");
        return -1;
    }

    // 绑定IP和端口
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = inet_addr(IP);
    int ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
    if (ret < 0)
    {
        perror("fail to bind");
        return -1;
    }

    // 监听
    ret = listen(sockfd, 10);
    if (ret < 0)
    {
        perror("fail to listen");
        return -1;
    }

    while (1)
    {
        // 接受连接
        struct sockaddr_in client_addr;
        socklen_t client_addr_len = sizeof(client_addr);
        int client_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
        if (client_sockfd < 0)
        {
            perror("fail to accept");
            continue; // 继续接受其他连接
        }

        printf("Client connected: %s:%d\n",
               inet_ntoa(client_addr.sin_addr),
               ntohs(client_addr.sin_port));

        // 接收数据
        pthread_t pid;
        pthread_create(&pid, NULL, (void *)stm_recv, client_sockfd);
        pthread_detach(pid);
        while (1)
        {
            //获取命令
            Cmd command;
            command.type = 1;
            char msg[1024];
            //打开消息队列
            msg_queue_recv("stm_command", (void *)(&command), sizeof(command), 1, 0);
            strcpy(msg,command.commend);
            printf("msg: %s\n",msg);
            // 发送命令
            send(client_sockfd,msg,sizeof(msg),1);
        }

        // 关闭客户端连接
        close(client_sockfd);
    }

    // 关闭服务器连接
    close(sockfd);
    return 0;
}
